/*
 * Copyright (C) 2018 The Asiainfo-Ability Authors
 *
 *      Licensed under the Apache License, Version 2.0 (the "License");
 *      you may not use this file except in compliance with the License.
 *      You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 *      Unless required by applicable law or agreed to in writing, software
 *      distributed under the License is distributed on an "AS IS" BASIS,
 *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *      See the License for the specific language governing permissions and
 *      limitations under the License.
 */

package org.asiainfo.ability.manager.controler;

import org.asiainfo.ability.base.utils.*;
import org.asiainfo.ability.gateway.cache.CacheService;
import org.asiainfo.ability.gateway.dao.AbilityDao;
import org.asiainfo.ability.gateway.dao.ServiceDao;
import org.asiainfo.ability.gateway.model.Instance;
import org.asiainfo.ability.gateway.model.Machine;
import org.asiainfo.ability.gateway.model.MicroService;
import org.asiainfo.ability.gateway.model.UserAbility;
import org.asiainfo.ability.gateway.vo.Page;
import org.asiainfo.ability.manager.service.AdminService;
import org.asiainfo.ability.manager.service.InstanceService;
import org.asiainfo.ability.manager.service.MsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: visen
 * @Date: 2018/1/28
 * @Description:
 */
@RestController
public class ServiceControler extends BaseControler {

    private Sequence seqUtils;

    @Autowired(required = false)
    private ServiceDao serviceDao;
    @Autowired(required = false)
    private AbilityDao abilityDao;

    @Autowired
    private AdminService adminService;

    @Autowired
    private InstanceService instanceService;

    @Autowired
    private MsService msService;

    @PostConstruct
    public void init() {
        this.seqUtils = SeqUtils.newInstance();
    }



    @RequestMapping(value = "/admin/service", method = RequestMethod.POST)
    public @ResponseBody
    String createService(@RequestBody MicroService microService, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            serviceDao.saveMicroService(microService);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success();
    }

    @RequestMapping(value = "/admin/service/{id}", method = RequestMethod.PUT)
    public @ResponseBody
    String updateUser(@PathVariable String id, @RequestBody MicroService microService, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            serviceDao.updateMicroService(microService);
            //dao.u(user);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success();
    }

    @RequestMapping(value = "/admin/service/{serviceName}", method = RequestMethod.DELETE)
    public @ResponseBody
    String deleteUser(@PathVariable String serviceName, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            serviceDao.deleteMicroService(serviceName);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success();
    }

    @RequestMapping(value = "/admin/service", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String listServices(HttpServletRequest request
            , HttpServletResponse response) {
        Page page = new Page();
        try {
            page.setPage(Integer.parseInt(request.getParameter("page")));
            page.setLimit(Integer.parseInt(request.getParameter("limit")));
            page.setPage((page.getPage()-1) * page.getLimit());
        } catch (Exception e){}

        try {
            return JsonUtils.toJSON(msService.listServicesViewData(page));
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }

    @RequestMapping(value = "/admin/service/{serviceName}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String loadService(@PathVariable String serviceName, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            MicroService microService = serviceDao.loadService(serviceName);
            return JsonUtils.toJSON(microService);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }


    @RequestMapping(value = "/admin/machine", method = RequestMethod.POST)
    public @ResponseBody
    String createMachine(@RequestBody Machine machine, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            machine.setId(String.valueOf(seqUtils.id()));
            serviceDao.saveMachine(machine);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success(machine.getId());
    }


    @RequestMapping(value = "/admin/machine/{id}", method = RequestMethod.DELETE)
    public @ResponseBody
    String deleteMachine(@PathVariable String id, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            serviceDao.deleteMachine(Long.parseLong(id));
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success();
    }

    @RequestMapping(value = "/admin/machine", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String listMachines(HttpServletRequest request
            , HttpServletResponse response) {
        try {
            List<Machine> machines = serviceDao.listMachines();
            Map ret = new HashMap<>();
            ret.put("data", machines);
            ret.put("code", 0);
            ret.put("msg", "");
            ret.put("count", machines.size());
            return JsonUtils.toJSON(ret);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }

    @RequestMapping(value = "/admin/machine/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String loadMachine(@PathVariable String id, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            Machine machine = serviceDao.loadMachine(Long.parseLong(id));
            return JsonUtils.toJSON(machine);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }

    @RequestMapping(value = "/admin/scale/instance", method = RequestMethod.POST)
    public @ResponseBody
    String scaleInstance(HttpServletRequest request
            , HttpServletResponse response) {
        List<Machine> machines = serviceDao.listMachines();
        return null;
    }

    @RequestMapping(value = "/admin/instance", method = RequestMethod.POST)
    public @ResponseBody
    String createInstance(@RequestBody Instance instance, HttpServletRequest request
            , HttpServletResponse response) {
        List<Instance> result = null;
        try {
            if ("1".equals(request.getParameter("mode"))) {
                String count = request.getParameter("count");
                result = instanceService.scaleInstance(instance, Integer.parseInt(count));
            } else {
                result = instanceService.manualScaleInstance(instance);
            }
        } catch (Exception e) {
            ExceptionUtils.logTrace(logger, e);
            return new Response("0", e.getMessage()).toJson();
        }
        return JsonUtils.toJSON(result);
    }


    @RequestMapping(value = "/admin/instance/{id}", method = RequestMethod.DELETE)
    public @ResponseBody
    String deleteInstance(@PathVariable String id, HttpServletRequest request
            , HttpServletResponse response) {
        try {

            String ids = request.getParameter("ids");
            String[] idArr = ids.split("_");
            instanceService.deleteInstances(idArr);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success();
    }

    @RequestMapping(value = "/admin/instances/{serviceName}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String listInstances(@PathVariable String serviceName, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            List<Instance> instances = serviceDao.listInstances(serviceName);
            for (Instance instance : instances) {
                Machine machine = serviceDao.loadMachine(Long.parseLong(instance.getMachineId()));
                if (machine != null) {
                    instance.setMachineInfo(machine.getName());
                    instance.setMachineAddr(machine.getIpAddress());
                } else {
                    instance.setMachineInfo("未知主机");
                }

            }
            Map ret = new HashMap<>();
            ret.put("data", instances);
            ret.put("code", 0);
            ret.put("msg", "");
            ret.put("count", instances.size());
            return JsonUtils.toJSON(ret);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }

    @RequestMapping(value = "/admin/instance/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String loadInstance(@PathVariable String id, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            Instance instance = serviceDao.loadInstance(Long.parseLong(id));
            if (instance != null) {
                return JsonUtils.toJSON(instance);
            }
            return null;
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }


    @RequestMapping(value = "/admin/ua", method = RequestMethod.POST)
    public @ResponseBody
    String addUserAbility(@RequestBody UserAbility userAbility, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            userAbility.setId(String.valueOf(seqUtils.id()));
            userAbility.setUpdateTime(new Date());
            serviceDao.saveUserAbility(userAbility);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success(userAbility.getId());
    }

    @RequestMapping(value = "/admin/ua/{id}", method = RequestMethod.PUT)
    public @ResponseBody
    String updateUserAbility(@RequestBody UserAbility userAbility, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            userAbility.setUpdateTime(new Date());

            serviceDao.updateUserAbility(userAbility);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success();
    }

    @RequestMapping(value = "/admin/ua/{id}", method = RequestMethod.DELETE)
    public @ResponseBody
    String delUserAbility(@PathVariable String id, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            serviceDao.deleteUserAbility(Long.parseLong(id));
            String clientId = request.getParameter("cid");
            String abilityName = request.getParameter("aname");
            adminService.remove(CacheService.CACHE_UAINFO, clientId, abilityName);
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
        return Response.success();
    }


    @RequestMapping(value = "/admin/ua/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String loadUserAbility(@PathVariable String id, HttpServletRequest request
            , HttpServletResponse response) {
        try {
            UserAbility userAbility = serviceDao.loadUserAbility(Long.parseLong(id));
            if (userAbility != null) {
                return JsonUtils.toJSON(userAbility);
            }
            return null;
        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }


    @RequestMapping(value = "/admin/uas/{clientId}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public @ResponseBody
    String loadUserAbilities(@PathVariable String clientId, HttpServletRequest request
            , HttpServletResponse response) {

        try {
            List<UserAbility> userAbilities = serviceDao.listUserAbilities(clientId);
            for (UserAbility userAbility : userAbilities) {
                ///abilityService.get
            }
            Map ret = new HashMap<>();
            ret.put("data", userAbilities);
            ret.put("code", 0);
            ret.put("msg", "");
            ret.put("count", userAbilities.size());
            return JsonUtils.toJSON(ret);

        } catch (Exception e) {
            logger.error("", e);
            return Response.error("0", null);
        }
    }
}
